<template>
  <div>
    <!-- Breadcrumb Navigation area -->
    <el-breadcrumb separator="/">
      <el-breadcrumb-item :to="{ path: '/home' }">Home</el-breadcrumb-item>
      <el-breadcrumb-item>User Management</el-breadcrumb-item>
      <el-breadcrumb-item>User List</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- Card view area -->
    <el-card>
      <!-- Search & add area -->
      <el-row :gutter="13">
        <el-col :span="7">
          <el-input
            placeholder="Please enter serch-key"
            v-model="queryInfo.query"
            clearable
            @clear="getUserList"
          >
            <el-button slot="append" icon="el-icon-search" @click="getUserList"></el-button>
          </el-input>
        </el-col>
        <el-col :span="4">
          <el-button type="primary" @click="addDialogVisible = !addDialogVisible">Add user</el-button>
        </el-col>
      </el-row>
      <!-- users list -->
      <el-table :data="userList" style="width: 100%" border stripe>
        <el-table-column type="index" label="#"></el-table-column>
        <el-table-column prop="username" label="User Name"></el-table-column>
        <el-table-column prop="email" label="Email"></el-table-column>
        <el-table-column prop="mobile" label="Mobile"></el-table-column>
        <el-table-column prop="role_name" label="Role"></el-table-column>
        <el-table-column label="State">
          <template slot-scope="scope">
            <el-switch v-model="scope.row.mg_state" @change="userStateChanged(scope.row)"></el-switch>
          </template>
        </el-table-column>
        <el-table-column label="Operating" width="299px">
          <template slot-scope="sp">
            <!-- edit btn -->
            <el-tooltip
              class="item"
              effect="dark"
              :content="'Edit ' + sp.row.username"
              placement="top-start"
              :enterable="false"
            >
              <el-button
                type="primary"
                icon="el-icon-edit"
                size="mini"
                @click="showEditUserDialog(sp.row)"
              >Edit</el-button>
            </el-tooltip>
            <!-- deltet btn -->
            <el-tooltip
              class="item"
              effect="dark"
              :content="'Delete ' + sp.row.username"
              placement="top-start"
              :enterable="false"
            >
              <el-button
                type="danger"
                icon="el-icon-delete"
                size="mini"
                @click="removeUserById(sp.row)"
              >Delete</el-button>
            </el-tooltip>
            <!-- set roles btn -->
            <el-tooltip
              class="item"
              effect="dark"
              :content="'Set Roles for ' + sp.row.username"
              placement="top-start"
              :enterable="false"
            >
              <el-button
                type="warning"
                icon="el-icon-setting"
                size="mini"
                @click="showSetRoleDialog(sp.row)"
              >Set Roles</el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <!-- paging -->
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="queryInfo.pagenum"
        :page-sizes="[1, 3, 5, 10, 50, 100]"
        :page-size="queryInfo.pagesize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      ></el-pagination>
    </el-card>

    <!-- add user dialog -->
    <el-dialog
      title="Please fill user info"
      :visible.sync="addDialogVisible"
      width="57%"
      @close="$refs.addFormRef.resetFields()"
    >
      <!-- main content -->
      <el-form :model="addForm" :rules="addFormRules" ref="addFormRef" label-width="90px">
        <el-form-item label="Username" prop="username">
          <el-input v-model="addForm.username"></el-input>
        </el-form-item>
        <el-form-item label="Password" prop="password">
          <el-input v-model="addForm.password" type="password"></el-input>
        </el-form-item>
        <el-form-item label="Email" prop="email">
          <el-input v-model="addForm.email"></el-input>
        </el-form-item>
        <el-form-item label="Mobile" prop="mobile">
          <el-input v-model="addForm.mobile"></el-input>
        </el-form-item>
      </el-form>
      <!-- footer -->
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">Cancel</el-button>
        <el-button type="info" @click="$refs.addFormRef.resetFields()">Reset</el-button>
        <el-button type="primary" @click="addUser">Sure</el-button>
      </span>
    </el-dialog>

    <!-- eidt user dialog -->
    <el-dialog
      title="Please fill user info"
      :visible.sync="editDialogVisible"
      width="57%"
      @close="$refs.editFormRef.resetFields()"
    >
      <!-- main content -->
      <el-form :model="editForm" :rules="addFormRules" ref="editFormRef" label-width="90px">
        <el-form-item label="Username" prop="username">
          <el-input v-model="editForm.username" disabled></el-input>
        </el-form-item>
        <el-form-item label="Email" prop="email">
          <el-input v-model="editForm.email"></el-input>
        </el-form-item>
        <el-form-item label="Mobile" prop="mobile">
          <el-input v-model="editForm.mobile"></el-input>
        </el-form-item>
      </el-form>
      <!-- footer -->
      <span slot="footer" class="dialog-footer">
        <el-button @click="editDialogVisible = false">Cancel</el-button>
        <el-button type="primary" @click="updateUser">Sure</el-button>
      </span>
    </el-dialog>

    <!-- set roles dialog -->
    <el-dialog title="Set Roles" :visible.sync="setRoleDialogVisible" width="57%" @close="closeSetRoleDialog">
      <div>
        <p>user: {{user.username}}</p>
        <p>role: {{user.role_name}}</p>
        <p>
          new role:
          <el-select v-model="selectedRoleId" placeholder="Please choose a role">
            <el-option
              v-for="item in roleList"
              :key="item.id"
              :label="item.roleName"
              :value="item.id"
            ></el-option>
          </el-select>
        </p>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="setRoleDialogVisible = false">Cancel</el-button>
        <el-button type="primary" @click="setRole">I Sure</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  data() {
    /* email validator */
    var checkEmail = (rule, val, callback) => {
      /* Regular expression of check email */
      const regEmail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/

      if (!regEmail.test(val)) {
        return callback(new Error('Please enter a legal email'))
      }
      /* legal email */
      callback()
    }
    /* mobile num validator */
    var checkMobile = (rule, val, callback) => {
      /* Regular expression of check mobile num */
      const regMobile = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/

      if (!regMobile.test(val)) {
        return callback(new Error('Please enter a legal mobile num'))
      }
      callback()
    }

    return {
      /* params for get user list data */
      queryInfo: {
        query: '',
        pagenum: 1,
        pagesize: 3
      },
      /* user form data for add */
      addForm: {
        username: '',
        password: '',
        email: '',
        mobile: ''
      },
      editForm: {
        id: '',
        username: '',
        email: '',
        mobile: ''
      },
      /* validate rules for addForm  */
      addFormRules: {
        username: [
          {
            required: true,
            message: 'Please enter a username',
            trigger: 'blur'
          },
          {
            min: 3,
            max: 13,
            message: 'length is 3 to 13 characters',
            trigger: 'blur'
          }
        ],
        password: [
          {
            required: true,
            message: 'Please enter a password',
            trigger: 'blur'
          },
          {
            min: 6,
            max: 19,
            message: 'length is 6 to 19 characters',
            trigger: 'blur'
          }
        ],
        email: [
          {
            required: true,
            message: 'Please enter a email',
            trigger: 'blur'
          },
          {
            validator: checkEmail,
            trigger: 'blur'
          }
        ],
        mobile: [
          {
            required: true,
            message: 'Please enter a mobile',
            trigger: 'blur'
          },
          {
            validator: checkMobile,
            trigger: 'blur'
          }
        ]
      },
      userList: [],
      total: 0,
      /* whether to show these dialogs */
      addDialogVisible: false,
      editDialogVisible: false,
      setRoleDialogVisible: false,
      /* curr operating user */
      user: {},
      roleList: [],
      isFirstGetRoleList: true,
      selectedRoleId: ''
    }
  },
  methods: {
    async getUserList() {
      const rs = await this.$http.get('users', { params: this.queryInfo })
      if (rs.meta.status !== 200) return this.$msg.error(rs.meta.msg)
      // console.log(JSON.stringify(rs.data))
      // this.$msg.success(rs.meta.msg)
      this.userList = rs.data.users
      this.total = rs.data.total
    },
    /* listen for page size changes event */
    handleSizeChange(newSize) {
      this.queryInfo.pagesize = newSize
      this.getUserList()
    },
    /* listen for page num changes event */
    handleCurrentChange(newPage) {
      this.queryInfo.pagenum = newPage
      this.getUserList()
    },
    /* listen for switch state change event */
    async userStateChanged(user) {
      const rs = await this.$http.put(`users/${user.id}/state/${user.mg_state}`)
      if (rs.meta.status !== 200) {
        user.mg_state = !user.mg_state
        return this.$msg.error(rs.meta.msg)
      }
      this.$msg.success(rs.meta.msg)
    },
    /* add a new user */
    addUser() {
      this.$refs.addFormRef.validate(async valid => {
        if (!valid) return
        const rs = await this.$http.post('/users', this.addForm)
        if (rs.meta.status !== 201) this.$msg.error(rs.meta.msg)
        this.$msg.success(rs.meta.msg)
        this.addDialogVisible = false
        this.getUserList()
      })
    },
    showEditUserDialog(user) {
      this.editDialogVisible = true
      for (const key in this.editForm) {
        this.editForm[key] = user[key]
      }
    },
    /* update a user */
    updateUser() {
      this.$refs.editFormRef.validate(async valid => {
        if (!valid) return
        const rs = await this.$http.put(
          `users/${this.editForm.id}`,
          this.editForm
        )
        if (rs.meta.status !== 200) this.$msg.error(rs.meta.msg)
        this.$msg.success(rs.meta.msg)
        this.editDialogVisible = false
        this.getUserList()
      })
    },
    async removeUserById(user) {
      /* Ask the user before deleting */
      /* if user cancel operation: result is  Promise Objest
       * so need catch to get error message & return
       *
       * if user confirm: result is a String
       */
      const confirmResult = await this.$confirm(
        'You will be deleting {' +
          user.username +
          '} user, the operation unrecoverable, you sure?',
        'Warning',
        {
          confirmButtonText: 'I Sure',
          cancelButtonText: 'Cancel',
          type: 'warning'
        }
      ).catch(err => err)

      /* if user cancel: tip & do noting */
      if (confirmResult !== 'confirm') {
        return this.$msg.info('Canceled')
      }
      /* if user confirm: do it! */
      const rs = await this.$http.delete(`/users/${user.id}`)
      if (rs.meta.status !== 200) return this.$msg.error(rs.meta.msg)
      this.$msg.success(rs.meta.msg)
      this.getUserList()
    },
    async showSetRoleDialog(user) {
      this.user = user
      /* get right list */
      if (this.isFirstGetRoleList) {
        console.log('first get role list...')
        this.isFirstGetRoleList = false
        var tryCount = 5
        while (tryCount--) {
          const rs = await this.$http.get('roles')
          /* faild, retry */
          if (rs.meta.status !== 200) {
            this.$msg.error(
              rs.meta.msg +
                '--> Retrying.. number of remaining attempts:' +
                tryCount
            )
            continue
          }
          /* success, break */
          this.roleList = rs.data
        }
      } else {
        /* not the first, take the local data, clone a new object ref */
        this.roleList = JSON.parse(JSON.stringify(this.roleList))
      }
      this.setRoleDialogVisible = true
    },
    async setRole() {
      if (!this.selectedRoleId) {
        return this.$msg.error('Please choose a role for user')
      }
      const rs = await this.$http.put(`users/${this.user.id}/role`, {
        rid: this.selectedRoleId
      })
      if (rs.meta.status !== 200) return this.$msg.error(rs.meta.msg)
      this.$msg.success(rs.meta.msg)
      this.getUserList()
      this.setRoleDialogVisible = false
    },
    closeSetRoleDialog() {
      this.selectedRoleId = ''
      this.user = {}
    }
  },
  /* when vue be created, auto callback this func */
  created() {
    /* get user list data from server */
    this.getUserList()
  }
}
</script>

<style lang="less" scoped>
.text {
  font-size: 14px;
}

.item {
  margin-bottom: 18px;
}

.clearfix:before,
.clearfix:after {
  display: table;
  content: '';
}
.clearfix:after {
  clear: both;
}
</style>
